﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.WindowsAPICodePack.Shell;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Markup;
using System.Collections;

namespace KazhOo.Sack.Controls.WPF
{
    /// <summary>
    /// Interaction logic for PathTextBlock.xaml
    /// </summary>

    //[ContentProperty("Root")]
    [ContentProperty("Items")]
    [TemplatePart(Name = "PART_ComboBox")]
    [TemplatePart(Name = "PART_Root")]
    [TemplatePart(Name = "PART_Progress")]
    public partial class BreadcrumbBar : Control, IAddChild //, INotifyPropertyChanged
    {

        static BreadcrumbBar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BreadcrumbBar), new FrameworkPropertyMetadata(typeof(BreadcrumbBar)));
        }


        public BreadcrumbBar()
        {
            Items = new ObservableCollection<object>();
        }



        public ObservableCollection<object> Items { get; set; }
        


        //------------------------------------------------------------------------------------------------------------------------------------------------------
        #region Path
        //------------------------------------------------------------------------------------------------------------------------------------------------------

        public static readonly DependencyProperty PathProperty =
            DependencyProperty.Register("Path", typeof(object), typeof(BreadcrumbBar), new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.AffectsMeasure |
            FrameworkPropertyMetadataOptions.AffectsRender |
            FrameworkPropertyMetadataOptions.AffectsArrange,
            OnPathPropertyChanged));

        //------------------------------------------------------------------------------------------------------------------------------------------------------

        public object Path
        {
            get { return (object)GetValue(PathProperty); }
            set { SetValue(PathProperty, value); }
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------

        private static void OnPathPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            BreadcrumbBar bar = d as BreadcrumbBar;
            bar.OnPathChanged(d, e.OldValue, e.NewValue);
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Occurs when the Path property is changed.
        /// </summary>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        protected virtual void OnPathChanged(object sender, object oldValue, object newValue)
        {
            if (newValue is string)
            {
                ShellObject newShellObject = ShellObject.FromParsingName(newValue as string);
                PopulateFolderCollection(newShellObject);
            }
            else if (newValue is ShellObject)
            {
                PopulateFolderCollection(newValue as ShellObject);
            }
            else if (newValue is IEnumerable)
            {
                PopulateFolderCollection(newValue as IEnumerable);
            }

            RaisePropertyChanged("Path");

            //newValue = GetFirstItem(newValue);
            //BreadcrumbItem oldPath = oldValue as BreadcrumbItem;
            //if (oldRoot != null)
            //{
            //    oldRoot.IsRoot = false;
            //}

            //if (newValue == null)
            //{
            //    RootItem = null;
            //    Path = null;
            //}
            //else
            //{
            //    BreadcrumbItem root = newValue as BreadcrumbItem;
            //    if (root == null)
            //    {
            //        root = BreadcrumbItem.CreateItem(newValue);
            //    }
            //    if (root != null)
            //    {
            //        root.IsRoot = true;
            //    }
            //    this.RemoveLogicalChild(oldValue);
            //    RootItem = root;
            //    if (root != null)
            //    {
            //        if (LogicalTreeHelper.GetParent(root) == null) this.AddLogicalChild(root);
            //    }
            //    SelectedItem = root != null ? root.DataContext : null;
            //    if (IsInitialized) SelectedBreadcrumb = root; else selectedBreadcrumb = root;
            //}
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------

        protected void PopulateFolderCollection(ShellObject newShellObject)
        {
            ShellObject CurrentPath = newShellObject;

            while (CurrentPath.IsFileSystemObject != false)
            {
                Items.Insert(0, CurrentPath);
                CurrentPath = CurrentPath.Parent;
            }
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------

        protected void PopulateFolderCollection(IEnumerable newCollection)
        {
            foreach (var item in newCollection)
            {
                Items.Insert(0, item);
            }
        }


        //------------------------------------------------------------------------------------------------------------------------------------------------------
        #endregion
        //------------------------------------------------------------------------------------------------------------------------------------------------------






        //------------------------------------------------------------------------------------------------------------------------------------------------------
        #region Progress
        //------------------------------------------------------------------------------------------------------------------------------------------------------

        public static readonly DependencyProperty ProgressValueProperty =
            DependencyProperty.Register("ProgressValue", typeof(double), typeof(BreadcrumbBar),
            new UIPropertyMetadata((double)0.0, ProgressValuePropertyChanged, CoerceProgressValue));

        public static readonly DependencyProperty ProgressMaximumProperty =
            DependencyProperty.Register("ProgressMaximum", typeof(double), typeof(BreadcrumbBar), new UIPropertyMetadata(100.0, null, CoerceProgressMaximum));

        public static readonly DependencyProperty ProgressMinimumProperty =
            DependencyProperty.Register("ProgressMinimum", typeof(double), typeof(BreadcrumbBar), new UIPropertyMetadata(0.0, null, CoerceProgressMinimum));

        public static readonly RoutedEvent ProgressValueChangedEvent = EventManager.RegisterRoutedEvent("ProgressValueChanged",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BreadcrumbBar));

        //------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Gets or sets the current progress indicator value.
        /// </summary>
        public double ProgressValue
        {
            get { return (double)GetValue(ProgressValueProperty); }
            set { SetValue(ProgressValueProperty, value); }
        }

        /// <summary>
        /// Gets or sets the maximum progress value.
        /// </summary>
        public double ProgressMaximum
        {
            get { return (double)GetValue(ProgressMaximumProperty); }
            set { SetValue(ProgressMaximumProperty, value); }
        }

        /// <summary>
        /// Gets or sets the minimum progess value.
        /// </summary>
        public double ProgressMimimum
        {
            get { return (double)GetValue(ProgressMinimumProperty); }
            set { SetValue(ProgressMinimumProperty, value); }
        }

        /// <summary>
        /// Occurs when the ProgressValue is changed.
        /// </summary>
        public event RoutedEventHandler ProgressValueChanged
        {
            add { AddHandler(BreadcrumbBar.ProgressValueChangedEvent, value); }
            remove { RemoveHandler(BreadcrumbBar.ProgressValueChangedEvent, value); }
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Check the desired value for ProgressValue and asure that it is between Minimum and Maximum:
        /// </summary>
        /// <param name="d"></param>
        /// <param name="baseValue"></param>
        /// <returns>The value between mimimum and maximum.</returns>
        static object CoerceProgressValue(DependencyObject d, object baseValue)
        {
            BreadcrumbBar bar = d as BreadcrumbBar;
            double value = (double)baseValue;
            if (value > bar.ProgressMaximum) value = bar.ProgressMaximum;
            if (value < bar.ProgressMimimum) value = bar.ProgressMimimum;

            return value;
        }

        static object CoerceProgressMaximum(DependencyObject d, object baseValue)
        {
            BreadcrumbBar bar = d as BreadcrumbBar;
            double value = (double)baseValue;
            if (value < bar.ProgressMimimum) value = bar.ProgressMimimum;
            if (value < bar.ProgressValue) bar.ProgressValue = value;
            if (value < 0) value = 0;

            return value;
        }

        static object CoerceProgressMinimum(DependencyObject d, object baseValue)
        {
            BreadcrumbBar bar = d as BreadcrumbBar;
            double value = (double)baseValue;
            if (value > bar.ProgressMaximum) value = bar.ProgressMaximum;
            if (value > bar.ProgressValue) bar.ProgressValue = value;

            return value;
        }

        static void ProgressValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //            RoutedPropertyChangedEventArgs<double> args = new RoutedPropertyChangedEventArgs<double>((double)e.OldValue, (double)e.NewValue,BreadcrumbBar.ProgessValueChangedEvent);
            RoutedEventArgs args = new RoutedEventArgs(BreadcrumbBar.ProgressValueChangedEvent);
            BreadcrumbBar bar = d as BreadcrumbBar;
            bar.RaiseEvent(args);
        }

        //------------------------------------------------------------------------------------------------------------------------------------------------------
        #endregion
        //------------------------------------------------------------------------------------------------------------------------------------------------------














        protected override void OnMouseLeave(MouseEventArgs e)
        {
            if (this.IsKeyboardFocusWithin) this.Focus();
            base.OnMouseLeave(e);
        }





        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        public void AddChild(object value)
        {
            throw new System.NotImplementedException();
        }

        public void AddText(string text)
        {
            throw new System.NotImplementedException();
        }
    }
}
